#pragma once

#include <iostream>
#include <memory>
#include <string>
#include <cstring>
#include <cstdlib>
#include "Logger.hpp"
#include "Comm.hpp"
#include "InetAddr.hpp"
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

static const int gdefaultsockfd = -1;
static const int gport = 8080;
static const int gbacklog = 8;

class EchoTcpSever
{
public:
    EchoTcpSever(uint16_t port = gport)
        : _listen_socket(gdefaultsockfd),
          _port(port)
    {
    }
    // 初始化
    void Init()
    {
        // 1. socket创建套接字
        _listen_socket = socket(AF_INET, SOCK_STREAM, 0);
        if (_listen_socket < 0)
        {
            LOG(LogLevel::ERROR) << "create socket error!";
            exit(SOCKET_CREATE_ERR);
        }
        LOG(LogLevel::INFO) << "create socket success!";

        // 2. bind连接
        InetAddr local(_port);
        if (bind(_listen_socket, local.Addr(), local.Length()) != 0)
        {
            LOG(LogLevel::ERROR) << "bind socket error!";
            exit(SOCKET_BIND_ERR);
        }
        LOG(LogLevel::INFO) << "bind socket success!";

        // 3. listen 监听连接
        if (listen(_listen_socket, gbacklog) != 0)
        {
            LOG(LogLevel::ERROR) << "listen socket error!";
            exit(SOCKET_LISTEN_ERR);
        }
        LOG(LogLevel::INFO) << "listen socket success!";
    }
    // 启动
    void Start()
    {
        while (true)
        {
            // 4. accept 接受连接
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            int sockfd = accept(_listen_socket, (struct sockaddr *)&peer, &len);
            if (sockfd < 0)
            {
                LOG(LogLevel::WARNING) << "accept error!";
            }
            InetAddr clientaddr(peer);
            LOG(LogLevel::INFO) << "get sockfd accept success, sockfd is : " << sockfd
                                << " client addr: " << clientaddr.ToString();
        }
    }
    ~EchoTcpSever()
    {
    }

private:
    int _listen_socket;
    uint16_t _port;
};